package com.zxy.ziems.server.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxy.btp.common.exception.ConditionException;
import com.zxy.btp.common.response.PageResult;
import com.zxy.ziems.server.domain.Resource;
import com.zxy.ziems.server.domain.Role;
import com.zxy.ziems.server.domain.RoleResourceRel;
import com.zxy.ziems.server.dto.ResourceTree;
import com.zxy.ziems.server.dto.RoleDto;
import com.zxy.ziems.server.dto.RoleQueryDto;
import com.zxy.ziems.server.mapper.RoleMapper;
import com.zxy.ziems.server.service.RoleResourceRelService;
import com.zxy.ziems.server.service.RoleService;
import com.zxy.ziems.server.service.UserRoleRelService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author missrain
 * @date 2021/8/30 4:47 下午
 * @Email:wangsiyu-hq@boe.com.cn
 */
@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RoleResourceRelService roleResourceRelService;
    @Autowired
    private UserRoleRelService userRoleRelService;

    /**
     * 创建/修改角色
     *
     * @param roleDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addOrUpdate(RoleDto roleDto) {
        //判断角色名称是否重复
        checkNameIsExit(roleDto);
        Role role = new Role();
        BeanUtils.copyProperties(roleDto, role);
        if (StrUtil.isEmpty(roleDto.getRoleId())) {
            checkCode(roleDto);
            roleMapper.insert(role);
        } else {
            checkCode(roleDto);
            roleMapper.updateById(role);
            //删除原有的关联数据
            QueryWrapper<RoleResourceRel> query = new QueryWrapper<>();
            query.lambda().eq(RoleResourceRel::getRoleId, roleDto.getRoleId());
            roleResourceRelService.deleteByCondition(query);
        }
        //组装关联表数据
        List<String> resourceIdList = roleDto.getResourceIdList();
        if (ObjectUtil.isEmpty(resourceIdList) || resourceIdList.isEmpty()) {
            throw new ConditionException("请设置角色关联资源后再保存");
        }
        List<RoleResourceRel> list = new ArrayList<>();
        resourceIdList.stream().forEach(resourceId -> {
            RoleResourceRel roleResourceRel = new RoleResourceRel();
            roleResourceRel.setResourceId(resourceId);
            roleResourceRel.setRoleId(role.getRoleId());
            list.add(roleResourceRel);
        });
        roleResourceRelService.saveBatch(list);
        return role.getRoleId();
    }

    /**
     * 判断角色编码在同一公司同一产品内是否重复
     *
     * @param roleDto
     * @return
     */
    private void checkCode(RoleDto roleDto) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Role::getRoleCode, roleDto.getRoleCode())
                .ne(StrUtil.isNotBlank(roleDto.getRoleId()), Role::getRoleId, roleDto.getRoleId());
        List<Role> roleList = roleMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(roleList)) {
            throw new ConditionException("角色编码重复，请修改后再试");
        }
    }

    /**
     * 判断角色名称是否重复
     *
     * @param roleDto
     */
    private void checkNameIsExit(RoleDto roleDto) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(Role::getRoleId)
                .eq(Role::getRoleName, roleDto.getRoleName());
        if (StrUtil.isNotEmpty(roleDto.getRoleId())) {
            queryWrapper.lambda().notIn(Role::getRoleId, roleDto.getRoleId());
        }
        List<Role> list = roleMapper.selectList(queryWrapper);
        if (ObjectUtil.isNotEmpty(list) && !list.isEmpty()) {
            throw new ConditionException("该角色名称已被占用，请重新设置！");
        }
    }

    /**
     * 删除角色
     *
     * @param roleId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String roleId) {
        //查询用户角色关联表，有关联数据不允许删除
        userRoleRelService.checkIsRel(roleId);
        //删除角色-资源关联数据
        roleResourceRelService.removeById(roleId);
        //删除角色
        roleMapper.deleteById(roleId);

    }

    /**
     * 角色分页列表
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public PageResult<Role> pageList(RoleQueryDto dto) {
        Page<Role> rolePage = new Page<>(dto.getPageNo(), dto.getPageSize());
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(StrUtil.isNotEmpty(dto.getRoleName()), Role::getRoleName, dto.getRoleName());
        Page<Role> page = roleMapper.selectPage(rolePage, queryWrapper);
        return new PageResult<>(page.getTotal(), page.getRecords());
    }

    /**
     * 查看角色详情/修改角色回显
     *
     * @param roleId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public RoleDto detail(String roleId) {
        //查询角色详情
        Role role = roleMapper.selectById(roleId);
        List<RoleResourceRel> roleResourceRels = roleResourceRelService.roleResourceRelListByRoleId(roleId);
        //查询已关联的资源信息
        List<ResourceTree> resourceTreeList = roleResourceRelService.listByRoleId(roleId);
        RoleDto roleDto = new RoleDto();
        BeanUtils.copyProperties(role, roleDto);
        roleDto.setResourceTreeList(resourceTreeList);
        roleDto.setResourceIdList(roleResourceRels.stream().map(RoleResourceRel::getResourceId).collect(Collectors.toList()));
        return roleDto;
    }

    /**
     * 查询所有角色
     *
     * @param roleQueryDto
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<Role> list(RoleQueryDto roleQueryDto) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .like(StrUtil.isNotEmpty(roleQueryDto.getRoleName()), Role::getRoleName, roleQueryDto.getRoleName());
        return roleMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional(readOnly = true)
    public List<ResourceTree> getLoginMenu(String userId) {
        //查询当前登录人的角色idList
        List<String> roleIdList = userRoleRelService.selectRoleIdList(userId);
        if (CollectionUtil.isNotEmpty(roleIdList)) {
            //根据角色idList查询资源idList
            return roleResourceRelService.listByRoleId(roleIdList);
        }
        return new ArrayList<>();
    }

    /**
     * 根据角色id查询角色
     *
     * @param ids
     * @return
     */
    @Override
    public List<Role> listByIds(Collection<? extends Serializable> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        //查询当前登录人的角色idList
        return roleMapper.selectListByIds(ids);
    }


    @Override
    @Transactional(readOnly = true)
    public List<ResourceTree> getAllResourceTree() {
        return roleResourceRelService.getAllResourceTree();
    }

    @Override
    public List<Resource> listByUserId(String userId) {
        //查询当前登录人的角色idList
        List<String> roleIdList = userRoleRelService.selectRoleIdList(userId);
        if (CollectionUtil.isEmpty(roleIdList)) {
            return new ArrayList<>();
        }
        return roleResourceRelService.listByRoleIds(roleIdList);
    }

    @Override
    public List<RoleResourceRel> roleResourceRelListByUserId(String userId) {
        //查询当前登录人的角色idList
        List<String> roleIdList = userRoleRelService.selectRoleIdList(userId);
        if (CollectionUtil.isEmpty(roleIdList)) {
            return new ArrayList<>();
        }
        return roleResourceRelService.roleResourceRelListByRoleIds(roleIdList);
    }
}
